package org.devio.`as`.proj.common.flutter

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import io.flutter.FlutterInjector
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.FlutterJNI
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.embedding.engine.loader.FlutterLoader
import org.devio.`as`.proj.common.view.HiImageViewPlugin
import org.devio.hi.library.log.HiLog
import org.devio.hi.library.util.HiFileUtil

/*
*Flutter 优化提升加载速度，实现秒开Flutter模块
* 1.如何让预加载不损失"首页"性能
* 2.如何实例化多个Flutter引擎并分别加载不同的dart 入口文件
* */
class HiFlutterCacheManager private constructor() {

    /**
     * 伴生对象,保持单例
     */
    companion object {

        //收藏页面,默认是flutter启动的主入口
        const val MODULE_NAME_FAVORITE = "main"

        //推荐页面
        const val MODULE_NAME_RECOMMEND = "recommend"

        @JvmStatic
        @get:Synchronized
        var instance: HiFlutterCacheManager? = null
            get() {
                if (field == null) {
                    field = HiFlutterCacheManager()
                }
                return field
            }
            private set
    }


    /**
     * 空闲时-预加载Flutter
     */
    fun preLoad(context: Context) {
        /*
        // TODO: 热更新代码,更新libappfix.so文件
        val messageQueue = Looper.myQueue()
        HiFileUtil.copyAssetsFileToFilesDir(context, HiFlutterLoader.FIX_SO, listener = {
            //在线程空闲时执行预加载任务
            messageQueue.addIdleHandler {
                initFlutterEngine(context, MODULE_NAME_FAVORITE)
                initFlutterEngine(context, MODULE_NAME_RECOMMEND)
                false
            }

        })
        */
        //在线程空闲时执行预加载任务
        Looper.myQueue().addIdleHandler {
            initFlutterEngine(context, MODULE_NAME_FAVORITE)
            initFlutterEngine(context, MODULE_NAME_RECOMMEND)
            false
        }
    }

    // 是否缓存过
    fun hasCached(moduleName: String): Boolean {
        return FlutterEngineCache.getInstance().contains(moduleName)
    }

    /**
     * 初始化Flutter
     */
    private fun initFlutterEngine(context: Context, moduleName: String): FlutterEngine {

        val flutterLoader: FlutterLoader = HiFlutterLoader()
        // val flutterLoader: FlutterLoader = FlutterInjector.instance().flutterLoader()
        HiLog.e("moduleName:$moduleName")
        //flutter 引擎
        val flutterEngine = FlutterEngine(context, flutterLoader, FlutterJNI())
        //插件注册要紧跟引擎初始化之后，否则会有在dart中调用插件因为还未初始化完成而导致的时序问题
        HiFlutterBridge.init(flutterEngine)
        HiImageViewPlugin.registerWith(flutterEngine);
        flutterEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint(
                flutterLoader.findAppBundlePath(),
                moduleName
            )
        )
        //存到引擎缓存中
        FlutterEngineCache.getInstance().put(moduleName, flutterEngine)
        return flutterEngine
    }

    /**
     * Dart VM预热
     */
    fun preLoadDartVM(context: Context) {
        val settings = FlutterLoader.Settings()
        FlutterLoader.getInstance().startInitialization(context, settings);
        val mainHandler = Handler(Looper.getMainLooper())
        FlutterLoader.getInstance()
            .ensureInitializationCompleteAsync(context, arrayOf(), mainHandler) {
                HiLog.i("Flutter preLoadDartVM done")
            }
    }

    /**
     * 获取预加载的flutterEngine
     */
    fun getCachedFlutterEngine(context: Context?, moduleName: String): FlutterEngine {
        var flutterEngine = FlutterEngineCache.getInstance()[moduleName]
        if (flutterEngine == null && context != null) {
            flutterEngine = initFlutterEngine(context, moduleName)
        }
        return flutterEngine!!
    }

    /**
     * 销毁FlutterEngine
     */
    fun destroyCached(moduleName: String) {
        val map = FlutterEngineCache.getInstance()
        if (map.contains(moduleName)) {
            map[moduleName]?.apply {
                destroy()
            }
            map.remove(moduleName)
        }
    }
}